package com.tennis.tennisreservation.controller;

import com.tennis.tennisreservation.common.Result;
import com.tennis.tennisreservation.config.WxPayConfig;
import com.tennis.tennisreservation.entity.Order;
import com.tennis.tennisreservation.service.OrderService;
import com.tennis.tennisreservation.service.PaymentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.UUID;
import java.util.Base64;
import java.security.Signature;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.security.PrivateKey;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.List;

/**
 * 微信支付控制器
 */
@RestController
@RequestMapping("/api/pay")
@RequiredArgsConstructor
@Slf4j
public class PaymentController {

    private final PaymentService paymentService;
    private final ObjectMapper objectMapper;
    private final WxPayConfig wxPayConfig;
    private final OrderService orderService;

    /**
     * 统一下单（JSAPI）
     */
    @PostMapping("/jsapi")
    public Result<Map<String, String>> createJsapiOrder(@RequestParam String openid,
                                                      @RequestParam Long amount,
                                                      @RequestParam String description) {
        try {
            log.info("发起微信支付统一下单: openid={}, amount={}, description={}", openid, amount, description);
            Map<String, String> result = paymentService.createJsapiOrder(openid, amount, description);
            log.info("统一下单成功，返回参数: {}", result);
            return Result.success(result);
        } catch (Exception e) {
            log.error("统一下单失败: {}", e.getMessage(), e);
            return Result.fail("创建支付订单失败: " + e.getMessage());
        }
    }

    /**
     * 支付结果通知接口
     */
    @PostMapping("/notify")
    public String handleWxPayNotify(@RequestBody String notifyData, HttpServletRequest request) {
        try {
            log.info("收到微信支付回调通知: {}", notifyData);
            
            // 解析通知数据
            Map<String, Object> notifyMap = objectMapper.readValue(notifyData, Map.class);
            
            // 验证签名（需要使用微信平台证书）
            // ... 验签逻辑 ...
            
            // 处理支付结果
            if (notifyMap.containsKey("resource")) {
                Map<String, Object> resource = (Map<String, Object>) notifyMap.get("resource");
                
                // 解密通知数据
                String ciphertext = (String) resource.get("ciphertext");
                String nonce = (String) resource.get("nonce");
                String associatedData = (String) resource.get("associated_data");
                
                // 使用API v3密钥解密
                String plaintext = decryptResource(ciphertext, nonce, associatedData, wxPayConfig.getPay().getApiV3Key());
                Map<String, Object> resourceMap = objectMapper.readValue(plaintext, Map.class);
                
                // 获取订单号和支付状态
                String outTradeNo = (String) resourceMap.get("out_trade_no");
                String tradeState = (String) resourceMap.get("trade_state");
                
                // 更新订单状态
                if ("SUCCESS".equals(tradeState)) {
                    // OrderService中没有直接通过订单号查询的方法，这里需要遍历查找
                    List<Order> allOrders = orderService.getOrdersByStatus("normal");
                    for (Order order : allOrders) {
                        // 根据Order实体类，使用id作为订单号进行匹配
                        // 注意：实际项目中建议在Order类中添加outTradeNo字段
                        if (order.getId() != null && order.getId().toString().equals(outTradeNo)) {
                            orderService.updatePayStatus(order.getId(), "paid");
                            log.info("订单 {} 支付成功", outTradeNo);
                            break;
                        }
                    }
                }
            }
            
            log.info("支付回调处理成功");
            // 返回成功消息给微信支付平台
            return "{\"code\":\"SUCCESS\",\"message\":\"成功\"}";
        } catch (Exception e) {
            log.error("支付回调处理失败: {}", e.getMessage(), e);
            // 返回失败消息
            return "{\"code\":\"FAIL\",\"message\":\"失败\"}";
        }
    }

    /**
     * 解密通知资源数据
     * 使用AES-GCM算法解密微信支付回调通知中的加密数据
     */
    private String decryptResource(String ciphertext, String nonce, String associatedData, String apiV3Key) throws Exception {
        final int TAG_LENGTH_BIT = 128;
        final int KEY_LENGTH_BYTE = 32;
        
        // 密文使用base64解码
        byte[] ciphertextBytes = Base64.getDecoder().decode(ciphertext);
        
        // 设置密钥
        byte[] keyBytes = apiV3Key.getBytes(StandardCharsets.UTF_8);
        byte[] fixedKeyBytes = new byte[KEY_LENGTH_BYTE];
        if (keyBytes.length > KEY_LENGTH_BYTE) {
            System.arraycopy(keyBytes, 0, fixedKeyBytes, 0, KEY_LENGTH_BYTE);
        } else {
            System.arraycopy(keyBytes, 0, fixedKeyBytes, 0, keyBytes.length);
        }
        SecretKeySpec key = new SecretKeySpec(fixedKeyBytes, "AES");
        
        // 设置GCM参数
        byte[] nonceBytes = nonce.getBytes(StandardCharsets.UTF_8);
        GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonceBytes);
        
        // 初始化cipher
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, key, spec);
        
        // 设置关联数据
        if (associatedData != null) {
            cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));
        }
        
        // 解密
        byte[] plaintext = cipher.doFinal(ciphertextBytes);
        
        // 返回明文
        return new String(plaintext, StandardCharsets.UTF_8);
    }
}
